/**
 * jims.
 */
package com.jims.master.modules.sys.security;

import com.jims.master.common.utils.EhCacheUtils;
import com.jims.master.common.utils.StringUtils;
import com.jims.master.modules.sys.entity.User;
import com.jims.master.modules.sys.service.SystemService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 表单验证（包含验证码）过滤类
 * @author ThinkGem
 * @version 2014-5-19
 */
@Service
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {

	public static final String DEFAULT_CAPTCHA_PARAM = "validateCode";
	public static final String DEFAULT_MOBILE_PARAM = "mobileLogin";
	public static final String DEFAULT_MESSAGE_PARAM = "message";
	public static final String DEFAULT_MOBILECODE_PARAM = "mobileCode";
	public static final String DEFAULT_BACKURL_PARAM = "backUrl";
	public static final String DEFAULT_LOGIN_TYPE= "type";
	public static final String DEFAULT_USER_TYPE= "userType";
    public static final String DEFAULT_AJAX= "ajaxIs";
	public static final String DEFAULT_OPENID= "openid";
	public static final String DEFAULT_QQOPENID="qqOpenid";

	private String captchaParam = DEFAULT_CAPTCHA_PARAM;
	private String mobileLoginParam = DEFAULT_MOBILE_PARAM;
	private String messageParam = DEFAULT_MESSAGE_PARAM;
	private String mobileCodeParam = DEFAULT_MOBILECODE_PARAM;
	private String backUrlParam = DEFAULT_BACKURL_PARAM;
	private String type = DEFAULT_LOGIN_TYPE;
	private String userTyep = DEFAULT_USER_TYPE;
    private String ajaxIs = DEFAULT_AJAX;
    private String openid=DEFAULT_OPENID;
    private String qqOpenid=DEFAULT_QQOPENID;

	@Autowired
	private SystemService systemService;
	@Override
	protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
		String username = getUsername(request);
		String password = getPassword(request);
		EhCacheUtils.put("password","user",password);
		if (password==null){
			password = "";
		}
		boolean rememberMe = isRememberMe(request);
		String host = StringUtils.getRemoteAddr((HttpServletRequest) request);
		String captcha = getCaptcha(request);
		boolean mobile = isMobileLogin(request);
		String mobileCode=getMobileCode(request);
		String backUrl = getBackUrl(request);
		String type= getType(request);
		String userType=getUserType(request);
        Boolean ajaxIs=getAjaxIs(request);
        String openid=getOpenid(request);
        String qqOpenid=getQqOpenid(request);
		return new UsernamePasswordToken(username, password.toCharArray(), rememberMe, host, captcha, mobile, mobileCode,backUrl,type,userType,ajaxIs,openid,qqOpenid);
	}

	public String getCaptchaParam() {
		return captchaParam;
	}

	protected String getCaptcha(ServletRequest request) {
		return WebUtils.getCleanParam(request, getCaptchaParam());
	}

	public String getMobileLoginParam() {
		return mobileLoginParam;
	}
	
	protected boolean isMobileLogin(ServletRequest request) {
        return WebUtils.isTrue(request, getMobileLoginParam());
    }
	
	public String getMessageParam() {
		return messageParam;
	}
	
	/**
	 * 登录成功之后跳转URL
	 */
	@Override
	public String getSuccessUrl() {
		return super.getSuccessUrl();
	}

	public String getMobileCodeParam() {
		return mobileCodeParam;
	}

	protected String getMobileCode(ServletRequest request) {
		return WebUtils.getCleanParam(request, getMobileCodeParam());
	}
	public String getBackUrlParam() {return backUrlParam;}

	protected String getBackUrl(ServletRequest request) {
		return WebUtils.getCleanParam(request, getBackUrlParam());
	}
	public String getType(ServletRequest request) {
		return WebUtils.getCleanParam(request, getTypeParam());
	}
	public String getTypeParam() {
		return type;
	}

	public String getUserType(ServletRequest request) {
		return WebUtils.getCleanParam(request, getUserTypeParam());
	}
	public String getUserTypeParam() {
		return userTyep;
	}

    public Boolean getAjaxIs(ServletRequest request) {
        return WebUtils.isTrue(request, getAjaxIsParam());
    }
    public String getAjaxIsParam() {
        return ajaxIs;
    }

	public String getOpenid(ServletRequest request) {
		return WebUtils.getCleanParam(request, getOpenidParam());
	}
	public String getOpenidParam() {return openid;}

	public String getQqOpenid(ServletRequest request) {
		return WebUtils.getCleanParam(request, getQqOpenidParam());
	}
	public String getQqOpenidParam() {return qqOpenid;}




	protected void issueSuccessRedirect(ServletRequest request,
			ServletResponse response,AuthenticationToken token) throws Exception {
            UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
            Map<Object,Object> map=new HashMap<Object, Object>();
            try {
                BeanInfo beanInfo = Introspector.getBeanInfo(usernamePasswordToken.getClass());
                PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
                for (PropertyDescriptor property : propertyDescriptors) {
                    String key = property.getName();
                    // 过滤class属性
                    if (!key.equals("class")) {
                        // 得到property对应的getter方法
                        Method getter = property.getReadMethod();
                        Object value = getter.invoke(usernamePasswordToken);
                        map.put(key, value);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            String url=getSuccessUrl();
		    WebUtils.issueRedirect(request, response, getSuccessUrl(),map, true);
	}
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
                                     ServletRequest request, ServletResponse response) throws Exception {
        issueSuccessRedirect(request, response,token);
        //we handled the success redirect directly, prevent the chain from continuing:
        return false;
    }
	/**
	 * 登录失败调用事件
	 */
	@Override
	protected boolean onLoginFailure(AuthenticationToken token,
			AuthenticationException e, ServletRequest request, ServletResponse response) {
		String className = e.getClass().getName(), message = "";
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String loginName=usernamePasswordToken.getUsername();
		User user = systemService.getUserByLoginName(loginName);
		if (IncorrectCredentialsException.class.getName().equals(className)
				|| UnknownAccountException.class.getName().equals(className)){
            if("3".equals(usernamePasswordToken.getType())&&user!=null){
                message = "验证码输入有误, 请重试.";
            }else if(!"3".equals(usernamePasswordToken.getType())&&user==null){
				message = "用户名不存在，请重试.";
            }else{
				message = "用户或密码错误, 请重试.";
			}
		}
		else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")){
			message = StringUtils.replace(e.getMessage(), "msg:", "");
		}
		else{
			message = "系统出现点问题，请稍后再试！";
			e.printStackTrace(); // 输出到控制台
		}
        request.setAttribute(getFailureKeyAttribute(), className);
        request.setAttribute(getMessageParam(), message);
		request.setAttribute(getTypeParam(), getType(request));
        return true;
	}

}